/*
 * CfgFile.cpp
 *
 *  Created on: 2011-6-3
 *      Author: wugang
 */

#include "CfgFile.h"
#include <fstream>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define MAX_INI_FILE_SIZE 1024*16

CfgFile::CfgFile() {

}

CfgFile::~CfgFile() {

}

int CfgFile::LoadIniFile(const char *file, char *buf,int *file_size)
{
	FILE *in = NULL;
	int i=0;
	*file_size =0;

	assert(file !=NULL);
	assert(buf !=NULL);

	in = fopen(file,"r");
	if( NULL == in) {
		return 0;
	}

	buf[i]=fgetc(in);

	while( buf[i]!= (char)EOF) {
		i++;
		assert( i < MAX_INI_FILE_SIZE );
		buf[i]=fgetc(in);
	}

	buf[i]='\0';
	*file_size = i;

	fclose(in);
	return 1;
}

int CfgFile::newline(char c)
{
	return ('\n' == c ||  '\r' == c )? 1 : 0;
}

int CfgFile::endOfString(char c)
{
	return '\0'==c? 1 : 0;
}

int CfgFile::leftBarce(char c)
{
	return '[' == c? 1 : 0;
}

int CfgFile::rightBrace(char c )
{
	return ']' == c? 1 : 0;
}

int CfgFile::parseFile(const char *section, const char *key, const char *buf,int *sec_s,int *sec_e,
					  int *key_s,int *key_e, int *value_s, int *value_e)
{
	const char *p = buf;
	int i=0;

	assert(buf!=NULL);
	assert(section != NULL && strlen(section));
	assert(key != NULL && strlen(key));

	*sec_e = *sec_s = *key_e = *key_s = *value_s = *value_e = -1;

	while( !endOfString(p[i]) ) {
		//find the section
		if( ( 0==i ||  newline(p[i-1]) ) && leftBarce(p[i]) )
		{
			int section_start=i+1;

			//find the ']'
			do {
				i++;
			} while( !rightBrace(p[i]) && !endOfString(p[i]));

			if( 0 == strncmp(p+section_start,section, i-section_start)) {
				int newline_start=0;

				i++;

				//Skip over space char after ']'
				while(isspace(p[i])) {
					i++;
				}

				//find the section
				*sec_s = section_start;
				*sec_e = i;

				while( ! (newline(p[i-1]) && leftBarce(p[i]))
					&& !endOfString(p[i]) ) {
						int j=0;
						//get a new line
						newline_start = i;

						while( !newline(p[i]) &&  !endOfString(p[i]) ) {
							i++;
						}

						//now i  is equal to end of the line
						j = newline_start;

						if(';' != p[j]) //skip over comment
						{
							while(j < i && p[j]!='=') {
								j++;
								if('=' == p[j]) {
									if(strncmp(key,p+newline_start,j-newline_start)==0)
									{
										//find the key ok
										*key_s = newline_start;
										*key_e = j-1;

										*value_s = j+1;
										*value_e = i;

										return 1;
									}
								}
							}
						}

						i++;
				}
			}
		}
		else
		{
			i++;
		}
	}
	return 0;
}

int CfgFile::readCfgfileString( const char *section, const char *key,char *value,
						int size, const char *default_value, const char *file)
{
	char buf[MAX_INI_FILE_SIZE]={0};
	int file_size;
	int sec_s,sec_e,key_s,key_e, value_s, value_e;

	assert(section != NULL && strlen(section));
	assert(key != NULL && strlen(key));
	assert(value != NULL);
	assert(size > 0);
	assert(file !=NULL &&strlen(key));

	if(!LoadIniFile(file,buf,&file_size))
	{
		if(default_value!=NULL)
		{
			strncpy(value,default_value, size);
		}
		return 0;
	}

	if(!parseFile(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e))
	{
		if(default_value!=NULL)
		{
			strncpy(value,default_value, size);
		}
		return 0;
	}
	else
	{
		int cpcount = value_e -value_s;

		if( size-1 < cpcount)
		{
			cpcount =  size-1;
		}

		memset(value, 0, size);
		memcpy(value,buf+value_s, cpcount );
		value[cpcount] = '\0';

		return 1;
	}
}

int CfgFile::readCfgfileInt( const char *section, const char *key,int default_value,
					 const char *file)
{
	char value[32] = {0};
	if(!readCfgfileString(section,key,value, sizeof(value),NULL,file))
	{
		return default_value;
	}
	else
	{
		return atoi(value);
	}
}

